using System;

namespace FridgeCase
{
    public class Fridge
    {
        public char[,] Refrigerator = new char[4, 4];
        private int _maxLength = 5;
        private int _findLength = 7;

        public Fridge()
        {
            for (var i = 0; i < 4; i++)
                for (var j = 0; j < 4; j++)
                    Refrigerator[i, j] = '-';
        }

        public char[,] Clone4X4(char[,] fridgeClone)
        {
            var result = new char[4, 4];
            for (var i = 0; i < 4; i++)
                for (var j = 0; j < 4; j++)
                    result[i, j] = fridgeClone[i, j];
            return (result);
        }

        public string ConvertResult(int arg1, int arg2)
        {
            return arg1*4 + arg2 + 1 >= 10
                       ? Convert.ToString(arg1*4 + arg2 + 1)
                       : "0" + Convert.ToString(arg1*4 + arg2 + 1);
        }

        public bool IsDone(char[,] checkFridge)
        {
            for (var i = 0; i < 4; i++)
                for (var j = 0; j < 4; j++)
                    if (checkFridge[i, j] == '|')
                        return false;
            return true;
        }

        public char ReverseElement(char argElemRefr)
        {
            argElemRefr = argElemRefr == '-' ? '|' : '-';
            return argElemRefr;
        }

        public void ReverseLine(int row, int col)
        {
            if ((col < 0 || col > 3) || (row < 0 || row > 3))
                return;
            for (var i = 0; i < 4; i++)
            {
                Refrigerator[i, col] = ReverseElement(Refrigerator[i, col]);
                Refrigerator[row, i] = ReverseElement(Refrigerator[row, i]);
            }
            Refrigerator[row, col] = ReverseElement(Refrigerator[row, col]);
        }

        public char[,] ReverseLine(char[,] argumentFridge, int row, int col)
        {
            if ((col < 0 || col > 3) || (row < 0 || row > 3))
                return argumentFridge;
            var resultFridge = Clone4X4(argumentFridge);
            for (var i = 0; i < 4; i++)
            {
                resultFridge[i, col] = ReverseElement(resultFridge[i, col]);
                resultFridge[row, i] = ReverseElement(resultFridge[row, i]);
            }
            resultFridge[row, col] = ReverseElement(resultFridge[row, col]);
            return resultFridge;
        }

        private string Searcher(char[,] fridgeSearch, string rowCol, int currentLevel)
        {
            if (currentLevel > _maxLength || currentLevel >= _findLength)
                return "";
            var tempFridge = Clone4X4(fridgeSearch);
            if (IsDone(tempFridge))
            {
                _findLength = currentLevel;
                return rowCol;
            }
            var lookInFirstTime = false;
            string temp;
            var result = "";
            for (var i = 0; i < 4; i++)
                for (var j = 0; j < 4; j++)
                {
                    temp = Searcher(ReverseLine(tempFridge, i, j), 
                        ConvertResult(i, j), currentLevel + 1);
                    if (temp == "") continue;
                    if (lookInFirstTime == false)
                    {
                        lookInFirstTime = true;
                        result = temp;
                    }
                    else if (temp.Length < result.Length)
                        result = temp;
                }
            if (result != "")
                result += " " + rowCol;
            return result;
        }

        public string FindSolution()
        {
            if (IsDone(Refrigerator))
                return "Already done";
            var refr = Clone4X4(Refrigerator);
            var lookInFirstTime = false;
            string temp;
            var result = "";
            for (var i = 0; i < 4; i++)
                for (var j = 0; j < 4; j++)
                {
                    temp = Searcher(ReverseLine(refr, i, j), ConvertResult(i, j), 0);
                    if (temp == "") continue;
                    if (lookInFirstTime == false)
                    {
                        lookInFirstTime = true;
                        result = temp;
                    }
                    else if (temp.Length < result.Length)
                        result = temp;
                }

            _findLength = _maxLength;
            return result;
        }
    }
}